<?php
namespace wof;
use Ratchet\MessageComponentInterface;
use Ratchet\ConnectionInterface;
use wof\Game;
use wof\User;

class WOF implements MessageComponentInterface {
    protected $clients;
    protected $a_PlayerData = array();

    public function __construct() {
        $this->clients = new \SplObjectStorage;
    }

    public function onOpen(ConnectionInterface $conn) {
        // Store the new connection to send messages to later
        $this->clients->attach($conn);

        echo "New connection! ({$conn->resourceId})\n";
    }

    public function onMessage(ConnectionInterface $from, $msg) {
        $numRecv = count($this->clients) - 1;
        echo sprintf('Connection %d sending message "%s" to %d other connection%s' . "\n"
            , $from->resourceId, $msg, $numRecv, $numRecv == 1 ? '' : 's');

        
        // Call Game Controller
        $game = new Game($msg, $this->a_PlayerData, $from->resourceId);
        $a_RetMsg = $game->start();
        $sz_Control = $a_RetMsg['control'];
        $sz_Value = $a_RetMsg['value'];
        // store data based on data in Game class
        $this->a_PlayerData = $game->a_PlayerData;
        switch ($sz_Control) {
            case 'ready':
                // send ready action to client
                foreach ($this->clients as $client) {
                    $client->send(implode("%%C%%",$a_RetMsg));
                }
                // generate category and send to client
                $a_Cat = $game->cat();
                foreach ($this->clients as $client) {
                    $client->send("cat%%C%%" . $a_Cat['name']);
                }
                // generate quiz and send to client
                $a_Quiz = $game->quiz($a_Cat['id']);
                foreach ($this->clients as $client) {
                    $client->send(implode("%%C%%",$a_Quiz));
                }
                $this->a_PlayerData = $game->a_PlayerData;
                // Ativate turn and send to client
                foreach ($this->clients as $client) {
                    $client->send("turn%%C%%" . $this->a_PlayerData['play_turn_name']);
                }
                break;
            case 'spin':
                // send spin value to other clients
                foreach ($this->clients as $client) {
                    if ($from !== $client) {
                        // The sender is not the receiver, send to each client connected
                        $client->send(implode("%%C%%",$a_RetMsg));
                    }
                }
                $this->a_PlayerData = $game->a_PlayerData;
                break;
            case 'letter':
                // send letter positions to client
                foreach ($this->clients as $client) {
                    $client->send(implode("%%C%%",$a_RetMsg));
                }
                
                // Update score info and send to client
                $o_User = new User($this->a_PlayerData);
                $sz_RetMsg = "score%%C%%" . $o_User->getScoreList();
                foreach ($this->clients as $client) {
                    $client->send($sz_RetMsg);
                }
                $this->a_PlayerData = $o_User->a_PlayerData;
                break;
            case 'vowel':
                // send letter to client
                foreach ($this->clients as $client) {
                    $client->send(implode("%%C%%",$a_RetMsg));
                }
                
                // Update score info and send to client
                $o_User = new User($this->a_PlayerData);
                $sz_RetMsg = "score%%C%%" . $o_User->getScoreList();
                foreach ($this->clients as $client) {
                    $client->send($sz_RetMsg);
                }
                $this->a_PlayerData = $o_User->a_PlayerData;
                break;
            case 'user':
                // Validate user log-on and check limitation of player then send to clients
                foreach ($this->clients as $client) {
                    $client->send(implode("%%C%%",$a_RetMsg));
                }
                $this->a_PlayerData = $game->a_PlayerData;
                break;
            case 'turn':
                // Set turn to next user and send to client
                foreach ($this->clients as $client) {
                    $client->send(implode("%%C%%",$a_RetMsg));
                }
                $this->a_PlayerData = $game->a_PlayerData;
                break;
            case 'endround':
                // Update endround info and send to client
                $o_User = new User($this->a_PlayerData);
                $sz_RetMsg = "endround%%C%%" . $this->a_PlayerData['round'] . "%%S%%" . $o_User->endRound();
                foreach ($this->clients as $client) {
                    $client->send($sz_RetMsg);
                }
                $this->a_PlayerData = $o_User->a_PlayerData;
                // Update score info and send to clients
                $o_User = new User($this->a_PlayerData);
                $sz_RetMsg = "score%%C%%" . $o_User->getScoreList();
                foreach ($this->clients as $client) {
                    $client->send($sz_RetMsg);
                }
                $this->a_PlayerData = $o_User->a_PlayerData;
                
                // Generate and Send new quiz to clients
                $game = new Game($msg, $this->a_PlayerData, $from->resourceId);
                $a_Quiz = $game->quiz($this->a_PlayerData["cat-id"], $this->a_PlayerData["select-quiz-id"]);
                foreach ($this->clients as $client) {
                    $client->send(implode("%%C%%",$a_Quiz));
                }
                $this->a_PlayerData = $game->a_PlayerData;
                // Set turn to next user and send to client
                $game = new Game($msg, $this->a_PlayerData, $from->resourceId);
                $a_Ret = $game->loseturn();
                foreach ($this->clients as $client) {
                    $client->send(implode("%%C%%",$a_Ret));
                }
                $this->a_PlayerData = $game->a_PlayerData;
                $this->a_PlayerData['round']++;
                // Send End game to clients
                if ((int) $this->a_PlayerData['round'] > 3) {
                    $this->a_PlayerData['status'] = "";
                    foreach ($this->clients as $client) {
                        $client->send("endgame");
                    }
                    // TODO: Store to DB
                }
                break;
            case 'error':
                $from->send(implode("%%C%%",$a_RetMsg));
                break;
        }
    }

    public function onClose(ConnectionInterface $conn) {
        // Remove user in player list then send to clients
        $sz_RetMsg = "";
        $o_User = new User($this->a_PlayerData);
        $sz_RetMsg = "user%%C%%" . $o_User->removeUser($conn->resourceId);
        foreach ($this->clients as $client) {
            $client->send($sz_RetMsg);
        }
        $this->a_PlayerData = $o_User->a_PlayerData;
        // Reset status
        if (!$this->a_PlayerData['a_Player'] || count($this->a_PlayerData['a_Player']) < 1) {
            $this->a_PlayerData['status'] = "";
        }
        // The connection is closed, remove it, as we can no longer send it messages
        $this->clients->detach($conn);

        echo "Connection {$conn->resourceId} has disconnected\n";
    }

    public function onError(ConnectionInterface $conn, \Exception $e) {
        echo "An error has occurred: {$e->getMessage()}\n";

        $conn->close();
    }
}

?>